﻿using System;
using System.Runtime.InteropServices;

namespace Microsoft.Goldenlight.Collections
{
    /// <summary>
    /// 	Represents a node in a SinglyLinkedList. This class cannot be inherited.
    /// </summary>
    /// <typeparam name="T"> Specifies the element type of the linked list. </typeparam>
    [ComVisible(false)]
    public sealed class SinglyLinkedListNode<T>
    {
        #region Static Operations

        private static SinglyLinkedListNode<T> s_head;

        #region Allocate

        /// <summary>
        /// 	Allocates a instance of the SinglyLinkedListNode class, containing the default value.
        /// </summary>
        /// <returns> A new instance of the SinglyLinkedListNode class. </returns>
        public static SinglyLinkedListNode<T> Allocate()
        {
            return Allocate(default(T));
        }

        /// <summary>
        /// 	Allocates a instance of the SinglyLinkedListNode class, containing the specified value.
        /// </summary>
        /// <param name="value"> The value to contain in the SinglyLinkedListNode. </param>
        /// <returns> A new instance of the SinglyLinkedListNode class. </returns>
        public static SinglyLinkedListNode<T> Allocate(T value)
        {
            if (s_head != null)
            {
                var allocatedNode = s_head;
                s_head = s_head.Next;
                allocatedNode.Value = value;
                allocatedNode.Next = null;
                return allocatedNode;
            }
            return new SinglyLinkedListNode<T>(value);
        }

        /// <summary>
        /// 	Allocates a instance of the SinglyLinkedListNode class, containing the specified value.
        /// </summary>
        /// <param name="list"> A reference to the SinglyLinkedList that the SinglyLinkedListNode belongs to, or null if the SinglyLinkedListNode is not linked. </param>
        /// <param name="value"> The value to contain in the SinglyLinkedListNode. </param>
        /// <returns> A new instance of the SinglyLinkedListNode class. </returns>
        public static SinglyLinkedListNode<T> Allocate(SinglyLinkedList<T> list, T value)
        {
            if (s_head != null)
            {
                var allocatedNode = s_head;
                s_head = s_head.Next;
                allocatedNode.List = list;
                allocatedNode.Value = value;
                allocatedNode.Next = null;
                return allocatedNode;
            }
            return new SinglyLinkedListNode<T>(list, value);
        }

        #endregion

        #region Free

        /// <summary>
        /// 	Recycle the instance of the SinglyLinkedListNode class, containing the specified value.
        /// </summary>
        /// <param name="node"> The SinglyLinkedListNode which to free. </param>
        public static void Free(SinglyLinkedListNode<T> node)
        {
            if (node == null)
            {
                throw new ArgumentNullException("node");
            }
            node.Value = default(T);
            node.List = null;
            node.Next = s_head;
            s_head = node;
        }

        #endregion

        #endregion

        #region Fields & Properties

        /// <summary>
        /// 	The value contained in the node.
        /// </summary>
        public T Value;

        /// <summary>
        /// 	A reference to the SinglyLinkedList that the SinglyLinkedListNode belongs to, or null if the SinglyLinkedListNode is not linked.
        /// </summary>
        public SinglyLinkedList<T> List;

        /// <summary>
        /// 	A reference to the next node in the SinglyLinkedList, or null if the current node is the last element of the SinglyLinkedList.
        /// </summary>
        public SinglyLinkedListNode<T> Next;

        #endregion

        #region Constructors

        /// <summary>
        /// 	Initializes a new instance of the SinglyLinkedListNode class, containing the specified value.
        /// </summary>
        /// <param name="value"> The value to contain in the SinglyLinkedListNode. </param>
        public SinglyLinkedListNode(T value)
        {
            Value = value;
        }

        /// <summary>
        /// 	Initializes a new instance of the SinglyLinkedListNode class, containing the specified value.
        /// </summary>
        /// <param name="list"> A reference to the SinglyLinkedList that the SinglyLinkedListNode belongs to, or null if the SinglyLinkedListNode is not linked. </param>
        /// <param name="value"> The value to contain in the SinglyLinkedListNode. </param>
        public SinglyLinkedListNode(SinglyLinkedList<T> list, T value)
        {
            List = list;
            Value = value;
        }

        #endregion
    }
}